/**
 * @type {HTMLCanvasElement}
 */
function getProgram(gl, { v, f }) {
  // 设置清空颜色缓冲区时的颜色
  gl.clearColor(1.0, 1.0, 1.0, 1.0)

  // 清空颜色缓冲区
  gl.clear(gl.COLOR_BUFFER_BIT)

  // 初始化shader程序
  const program = initWebGL(gl, v, f)
  // 告诉WebGL使用我们刚刚初始化的这个程序
  gl.useProgram(program)

  return program
}

/**
 *
 * @param {WebGLRenderingContext} gl
 * @param {string} type
 * @param {string} source
 */
function createShader(gl, type, source) {
  // 创建 shader 对象
  let shader = gl.createShader(type)
  // 往 shader 中传入源代码
  gl.shaderSource(shader, source)
  // 编译 shader
  gl.compileShader(shader)
  // 判断 shader 是否编译成功
  let success = gl.getShaderParameter(shader, gl.COMPILE_STATUS)
  if (success) {
    return shader
  }
  // 如果编译失败，则打印错误信息
  console.log(gl.getShaderInfoLog(shader))
  gl.deleteShader(shader)
}

/**
 *
 * @param {WebGLRenderingContext} gl
 * @param {WebGLShader} vertexShader
 * @param {WebGLShader} fragmentShader
 */
function createProgram(gl, vertexShader, fragmentShader) {
  // 创建 program 对象
  let program = gl.createProgram()
  // 往 program 对象中传入 WebGLShader 对象
  gl.attachShader(program, vertexShader)
  gl.attachShader(program, fragmentShader)
  // 链接 program
  gl.linkProgram(program)
  // 判断 program 是否链接成功
  let success = gl.getProgramParameter(program, gl.LINK_STATUS)
  if (success) {
    return program
  }
  // 如果 program 链接失败，则打印错误信息
  console.log(gl.getProgramInfoLog(program))
  gl.deleteProgram(program)
}
/**
 *
 * @param {WebGLRenderingContext} gl
 * @param {string} vertexSource
 * @param {string} fragmentSource
 */
function initWebGL(gl, vertexSource, fragmentSource) {
  // 根据源代码创建顶点着色器
  let vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexSource)
  // 根据源代码创建片元着色器
  let fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentSource)
  // 创建 WebGLProgram 程序
  let program = createProgram(gl, vertexShader, fragmentShader)
  return program
}

// 实现一个点
function realizedPoint(program, gl, point = [0.0, 0.0, 0.0]) {
  // 获取shader中a_position的地址
  const a_position = gl.getAttribLocation(program, "a_position")
  // 往a_position这个地址中传值
  gl.vertexAttrib3f(a_position, 0.0, 0.0, 0.0)
  // 开始绘制，绘制类型是gl.POINTS绘制点，0表示第一个点的索引，1表示共绘制几个点
  gl.drawArrays(gl.POINTS, 0, 1)
}

//平移矩阵
function getTranslateMatrix(x = 0, y = 0, z = 0) {
  return new Float32Array([
    1.0,
    0.0,
    0.0,
    0.0,
    0.0,
    1.0,
    0.0,
    0.0,
    0.0,
    0.0,
    1.0,
    0.0,
    x,
    y,
    z,
    1.0,
  ])
}
//缩放矩阵
function getScaleMatrix(x = 0, y = 0, z = 0) {
  return new Float32Array([
    x,
    0.0,
    0.0,
    0.0,
    0.0,
    y,
    0.0,
    0.0,
    0.0,
    0.0,
    z,
    0.0,
    0.0,
    0.0,
    0.0,
    1,
  ])
}
//旋转矩阵
function getRotataMatrix(deg = 0) {
  return new Float32Array([
    Math.cos(deg),
    Math.sin(deg),
    0.0,
    0.0,
    -Math.sin(deg),
    Math.cos(deg),
    0.0,
    0.0,
    0.0,
    0.0,
    1.0,
    0.0,
    0.0,
    0.0,
    0.0,
    1,
  ])
}
//矩阵复合函数
function mixMatrix(A, B) {
  const res = new Float32Array(16)

  for (let i = 0; i < 4; i++) {
    res[i] = A[i] * B[0] + A[i + 4] * B[1] + A[i + 8] * B[2] + A[i + 12] * B[3]
    res[i + 4] =
      A[i] * B[4] + A[i + 4] * B[5] + A[i + 8] * B[6] + A[i + 12] * B[7]
    res[i + 8] =
      A[i] * B[8] + A[i + 4] * B[9] + A[i + 8] * B[10] + A[i + 12] * B[11]
    res[i + 12] =
      A[i] * B[12] + A[i + 4] * B[13] + A[i + 8] * B[14] + A[i + 12] * B[15]
  }

  return res
}
